﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Xml;
using Tomers.WPF.Localization;

namespace XmlStudio.Localization {
	/// <summary>
	/// Class for localization.
	/// </summary>
	public class XmlLanguageDictionary : LanguageDictionary {
		#region Member fields
		private Dictionary<string, Dictionary<string, string>> data = new Dictionary<string, Dictionary<string, string>>();
		private string path;
		private string cultureName;
		private string englishName;
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the path.
		/// </summary>
		public string Path {
			get { return path; }
			set { path = value; }
		}

		/// <summary>
		/// Gets the culture name.
		/// </summary>
		public override string CultureName {
			get { return cultureName; }
		}

		/// <summary>
		/// Gets the English name.
		/// </summary>
		public override string EnglishName {
			get { return englishName; }
		}
		#endregion

		#region Constructors
		/// <summary>
		/// Initializes a new instance of the XmlLanguageDictionary.
		/// </summary>
		/// <param name="path">path to the file with the dictionary.</param>
		public XmlLanguageDictionary(string path) {
			if (!File.Exists(path)) {
				string workingDir = Environment.CurrentDirectory;
				throw new ArgumentException(string.Format("File {0} doesn't exist. Current working dir: {1}", path, workingDir));
			}
			this.path = path;
		}
		#endregion

		#region Event handlers
		/// <summary>
		/// Overrides defaul OnLoad event.
		/// </summary>
		protected override void OnLoad() {
			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.Load(path);
			if (xmlDocument.DocumentElement.Name != "Dictionary") {
				throw new XmlException("Invalid root element. Must be Dictionary");
			}
			XmlAttribute englishNameAttribute = xmlDocument.DocumentElement.Attributes["EnglishName"];
			if (englishNameAttribute != null) {
				englishName = englishNameAttribute.Value;
			}
			XmlAttribute cultureNameAttribute = xmlDocument.DocumentElement.Attributes["CultureName"];
			if (cultureNameAttribute != null) {
				cultureName = cultureNameAttribute.Value;
			}
			foreach (XmlNode node in xmlDocument.DocumentElement.ChildNodes) {
				if (node.Name == "Value") {
					Dictionary<string, string> innerData = new Dictionary<string, string>();
					foreach (XmlAttribute attribute in node.Attributes) {
						if (attribute.Name == "Id") {
							if (!data.ContainsKey(attribute.Value)) {
								data[attribute.Value] = innerData;
							}
						} else {
							innerData[attribute.Name] = attribute.Value;
						}
					}
				}
			}
		}

		/// <summary>
		/// Overrides the default OnUnload event.
		/// </summary>
		protected override void OnUnload() {
			data.Clear();
		}

		/// <summary>
		/// Overrides the defaul OnTranslate event.
		/// </summary>
		/// <param name="uid">uid</param>
		/// <param name="vid">vid</param>
		/// <param name="defaultValue">default value</param>
		/// <param name="type">Type</param>
		/// <returns>Returns translated value or null.</returns>
		protected override object OnTranslate(string uid, string vid, object defaultValue, Type type) {
			if (string.IsNullOrEmpty(uid)) {
				#region Trace
				Debug.WriteLine(string.Format("Uid must not be null or empty"));
				#endregion
				return defaultValue;
			}
			if (string.IsNullOrEmpty(vid)) {
				#region Trace
				Debug.WriteLine(string.Format("Vid must not be null or empty"));
				#endregion
				return defaultValue;
			}
			if (!data.ContainsKey(uid)) {
				#region Trace
				Debug.WriteLine(string.Format("Uid {0} was not found in the {1} dictionary", uid, EnglishName));
				#endregion
				return defaultValue;
			}
			Dictionary<string, string> innerData = data[uid];

			if (!innerData.ContainsKey(vid)) {
				#region Trace
				Debug.WriteLine(string.Format("Vid {0} was not found for Uid {1}, in the {2} dictionary", vid, uid, EnglishName));
				#endregion
				return defaultValue;
			}
			string textValue = innerData[vid];
			try {
				if (type == typeof(object)) {
					return textValue;
				} else {
					TypeConverter typeConverter = TypeDescriptor.GetConverter(type);
					object translation = typeConverter.ConvertFromString(textValue);
					return translation;
				}
			} catch (Exception ex) {
				#region Trace
				Debug.WriteLine(string.Format("Failed to translate text {0} in dictionary {1}:\n{2}", textValue, EnglishName, ex.Message));
				#endregion
				return null;
			}
		}
		#endregion		
	}
}
